package authuserpbkdf

import (
	"crypto/pbkdf2"
	"crypto/rand"
	"crypto/sha256"
	"encoding/hex"

	"gitee.com/tgodfather/utility/auth"
)

const (
	VALIDATOR_KEYLEN = 32
	VALIDATOR_ITER   = 100000
)

// login  	uesrname   	-  用户名
//
//			realPassword 	-  用户输入密码
//			inSalt		-  随机数 32位
//	       	inPassword   	-  提交时的密码字段
//						inPassword  =  hex2str(inSalt) + pbkdf2(sha256, inSalt , realPassword)
type UserValidator struct {
	username string //输入的username字段内容
	password string //输入的password字段内容

	inSalt []byte //从password 获得 inSalt = str2Hex(password[:32])  实际[16]byte
	inKey  string //从password 获得 inSalt = password[32:]

	keyLen int // 32，产生key的长度
	iter   int // 迭代次数 100000
}

func (v *UserValidator) VUsername() string {
	return v.username
}

// Password() string
func (v *UserValidator) VPassword() string {
	return v.password
}

func (v *UserValidator) Key() string {
	return v.inKey
}

func (v *UserValidator) GenerateKey(pass string) (string, error) {
	// 使用 PBKDF2 派生密钥
	key, err := pbkdf2.Key(sha256.New, pass, v.inSalt, v.iter, v.keyLen)
	keyStr := hex.EncodeToString(key)
	return keyStr, err
}

func NewUserValidator(username, password string, opt ...auth.ValidatorOption) auth.Validator {

	inUsername := username
	inPassword := ""
	realPassword := ""

	inKey := ""
	var inSalt []byte

	iter := VALIDATOR_ITER
	keyLen := VALIDATOR_KEYLEN

	opts := auth.NewValidatorOptions(opt...)

	if opts.NeedGenerate { // 需要生成，通常应用于客户端生成校验字符串场景
		realPassword = password
		//inPassword, _ = genterateInPassword(inUsername, realPassword)
		inSalt, inKey, _ = genterateInPassword(realPassword, iter, keyLen)
	} else { //不需要生成密码，提取salt 用于校验密码场景，
		inPassword = password
		inSalt, inKey, _ = parseInPassowrd(inPassword)
	}

	return &UserValidator{
		username: inUsername,
		password: inPassword,

		inSalt: inSalt,
		inKey:  inKey,

		iter:   iter,
		keyLen: keyLen,
	}
}

func genterateInPassword(realPass string, iter int, keyLen int) (inSalt []byte, inKey string, err error) {
	// 生成一个16字节的随机密钥
	salt := make([]byte, 16)
	if _, rErr := rand.Read(salt); rErr != nil {
		//fmt.Println("Error generating random key:", err)
		return nil, "", rErr
	}

	// 使用 PBKDF2 派生密钥
	key, _ := pbkdf2.Key(sha256.New, realPass, salt, iter, keyLen)
	inKey = hex.EncodeToString(key)

	return salt, inKey, nil
}

func parseInPassowrd(sPassword string) (inSalt []byte, inKey string, err error) {
	if len(sPassword) <= 32 {
		return nil, "", auth.ErrInvalidPasswordLength
	}

	saltStr := sPassword[:32]
	salt, dErr := hex.DecodeString(saltStr)
	if dErr != nil {
		return nil, "", dErr
	}

	inKey = sPassword[32:]

	return salt, inKey, nil
}
